package com.jiangyg.devtools.execute.code.parser;

import com.jiangyg.devtools.entity.code.BeanProperty;
import com.jiangyg.devtools.toolkit.Assert;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 类描述：建表语句的 Bean 属性解析器
 *
 * @author jiangyg
 * @version 1.0
 * @date 2023年09月22日
 */
public class SQLStringBeanPropertyParser extends AbstractPropertyParser {

    private String convertedSQLString = StringUtils.EMPTY;

    public SQLStringBeanPropertyParser(String input) {
        super(input);
    }

    @Override
    protected List<BeanProperty> parseBeanPropertyList() throws IOException {
        final String regex = "(?i)(?m)create\\s+table\\s+[a-zA-z0-9_]+\\s+\\((?<cls>([^;()]*(\\(\\d+(,\\d+)?\\))?[^;()]*?)*?)(\\s+primary\\s+key\\s+\\([^;()]+\\)[^;()]*)?\\)";
        final String cls = attemptObtainValueByRegex(new String[]{regex}, getSQLString(), "cls");
        return obtainBeanPropertyList(cls);
    }

    private List<BeanProperty> obtainBeanPropertyList(String cls) throws IOException {
        return Arrays.stream(cls.split(","))
                .filter(StringUtils::isNotBlank)
                .map(line -> {
                    final String[] split = line.trim().split(separator);
                    Assert.state(split.length > 0);

                    final String name = split[0];
                    final String type = split.length > 1 ? split[1] : StringUtils.EMPTY;
                    final String comment = obtainColumnComment(name);

                    return buildBeanProperty(name, type, comment);
                })
                .collect(Collectors.toList());
    }

    /**
     * 功能描述：尝试从SQL语句中获取表注释
     *
     * @return 表注释
     */
    @Override
    protected String parseTableComment() {
        // 先尝试 Oracle 语法获取表注释，再尝试 MySQL 语法获取表注释
        final String[] regexps = new String[]{
                "(?i)(?m)comment\\s+on\\s+table\\s+[u4e00-u9fa5_a-zA-Z0-9]+\\s+is\\s+'(?<tzn>[^']+)'",
                "(?i)(?m)create\\s+table\\s+[a-zA-z0-9_]+\\s+\\(([^;()]*(\\(\\d+(,\\d+)?\\))?[^;()]*)*\\)?[\\s\\S]+?comment\\s+=\\s+'(?<tzn>[^']+)'"
        };
        // 开始匹配
        return attemptObtainValueByRegex(regexps, getSQLString(), "tzn");
    }

    /**
     * 功能描述：尝试从SQL语句中获取字段注释
     *
     * @param fieldName 字段名
     * @return 字段注释
     */
    private String obtainColumnComment(String fieldName) {
        // 先尝试 Oracle 语法获取字段注释，再尝试 MySQL 语法获取字段注释
        final String[] regexps = new String[]{
                String.format("(?i)(?m)%s[^;(),']*([(]\\d+(,\\d+)?[)])?[^;(),']*?comment\\s+'(?<zdm>[^']+)'", fieldName),
                String.format("(?i)(?m)comment\\s+on\\s+column\\s+([u4e00-u9fa5_a-zA-Z0-9]+[.])?%s\\s+is\\s+'(?<tzn>[^']+)';", fieldName)
        };
        // 开始匹配
        return attemptObtainValueByRegex(regexps, getSQLString(), "zdm");
    }

    @Override
    protected String parseTableName() {
        final String regex = "(?i)(?m)create\\s+table\\s+(?<tn>[a-zA-z0-9_]+)\\s+";
        return attemptObtainValueByRegex(new String[]{regex}, getSQLString(), "tn");
    }

    private String getSQLString() {
        if (StringUtils.isBlank(convertedSQLString)) {
            this.convertedSQLString = input.replaceAll("`", "");
        }
        return convertedSQLString;
    }

    @Override
    public boolean support() {
        final String regex = "(?i)(?m)create\\s+table\\s+[a-zA-z0-9_]+\\s+\\([\\s\\S]+\\)[\\s\\S]+";
        final Pattern pattern = Pattern.compile(regex);
        final Matcher matcher = pattern.matcher(getSQLString());
        return matcher.find();
    }

}
